package com.apacheGzq.thread;

import org.apache.log4j.Logger;

import com.apacheGzq.constant.Constants;
import com.apacheGzq.main.MyServer;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;

/**
 * Created by gaozhiqiang .
 */
public class ListenTask implements Runnable {
    private static final Logger log = Logger.getLogger(ListenTask.class);

    private String threadName = "ListenTask-"+Thread.currentThread().getName();;
    private ExecutorService threadPool = null;

    public ListenTask(ExecutorService threadPool){
        this.threadPool = threadPool;
    };

    @Override
    public void run() {
        log.info("开始初始化服务器...");
        ServerSocketChannel server = null;
        Selector selector = null;
        try {
            server = ServerSocketChannel.open(); //获取Serversocket通道
            server.configureBlocking(false); //设置为非阻塞
            server.socket().bind(new InetSocketAddress(Constants.SERVERPORT), Constants.BACKLOG);
            selector = Selector.open();
            server.register(selector, SelectionKey.OP_ACCEPT); //将NIO通道绑定到选择器

        } catch (IOException e) {
            log.error("初始化服务器异常,系统退出!", e);
            System.exit(-1);
        }
        log.info("服务器初始化完成.开始在"+Constants.SERVERPORT+"端口监听，最大可接受连接数为:"+Constants.BACKLOG);

        while (MyServer.runStatus == MyServer.RUNNING) {
            try {
                int num = selector.select();
                if(num < 1) {
                    continue;
                }
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    iterator.remove();

                    if(key.isValid() && key.isAcceptable()) {
                        SocketChannel client = null;
                        try {
                            client = server.accept();
                            log.info("Accepted from client:" + client);
                            client.configureBlocking(false);
                            SelectionKey rKey = client.register(selector, SelectionKey.OP_READ);
                            rKey.attach("read_command");
                        } catch (IOException e) {
                            log.error("接受客户端连接请求异常!",e);
                            continue;
                        }
                    } else if(key.isValid() && key.isReadable()) {
                        SocketChannel client = (SocketChannel) key.channel();
                        client.configureBlocking(false);
                        String name = (String) key.attachment();
                        if("read_command".equals(name)) {
                            this.threadPool.execute(new ReadAndWriteTask(client));
                            key.cancel();
                        };
                    }
                }
            } catch (IOException e) {
                log.error("服务器异常退出！", e);
                System.exit(-2);
            }
        }

    }
}
